#include <windows.h>

typedef unsigned char u8;
typedef unsigned short int u16;

HANDLE hCom;

#include <stdio.h>


char WriteMux(u8 link, const char *bytes, u16 length)
{
	const char  *b = bytes;
	DWORD wbytes;
	BOOL bResult = TRUE;
	char buffer[64];
	char *pBuffer = &buffer[4];

	// encode to buffer
	buffer[0] = 0xbf;
	buffer[1] = link; /* {LINK} */
	while (b < bytes+length)
	{
		*pBuffer++ = *b++;	
	}
	buffer[2] = length>>8;
	buffer[3] = (char)length;
	*pBuffer++ = 0x00; /* {LINK} XOR OxFF */

	// send buffer
	b = &buffer[0];
	while (bResult  && (b < pBuffer))
	{
		Sleep(1);
		bResult = WriteFile(hCom,b,1,&wbytes, NULL);
		b++;
	}
	Sleep(1);
	printf("%c\n",bytes);
	return 0;
}

char OpenPort()
{
	DCB dcb;
	COMMTIMEOUTS timeouts;
	TCHAR *pcCommPort = TEXT("\\\\.\\COM3"); 

	//  Open a handle to the specified com port.
	hCom = CreateFile( pcCommPort,
		GENERIC_READ | GENERIC_WRITE,
		0,      //  must be opened with exclusive-access
		NULL,   //  default security attributes
		OPEN_EXISTING, //  must use OPEN_EXISTING
		0,      //  not overlapped I/O
		NULL ); //  hTemplate must be NULL for comm devices

	if (hCom == INVALID_HANDLE_VALUE) 
	{
		//  Handle the error.
		printf("CreateFile failed with error code %d\n", GetLastError());
		return (-1);
	}

	//  Initialize the DCB structure.
	SecureZeroMemory(&dcb, sizeof(DCB));
	dcb.DCBlength = sizeof(DCB);

	//  Set CommState
	GetCommState(hCom, &dcb);
	dcb.BaudRate = CBR_115200;    //  baud rate
	dcb.ByteSize = 8;             //  data size, xmit and rcv
	dcb.Parity   = NOPARITY;      //  parity bit
	dcb.StopBits = ONESTOPBIT;    //  stop bit
	SetCommState(hCom, &dcb);

	// Set timeouts
	GetCommTimeouts(hCom, &timeouts);
	timeouts.ReadIntervalTimeout = 1;
	timeouts.ReadTotalTimeoutConstant = 1000;
	timeouts.ReadTotalTimeoutMultiplier = 1;
	timeouts.WriteTotalTimeoutConstant = 1;
	SetCommTimeouts(hCom, &timeouts);

	return 1;
}




/* Return one byte, this is non blocking */
char Read(u8 *byte)
{
	DWORD nBytesRead;	
	BOOL bResult = ReadFile(hCom, byte, 1, &nBytesRead, NULL);

	if (bResult &&  nBytesRead == 1) 
	{ 
		//printf("RX: %c (%d)\n", *byte, *byte);
		return 1; 
	} 
	return 0;
}

char WriteLine(const char *bytes)
{
	const char  *b = bytes;
	u8 cr = '\n';
	DWORD wbytes;
	BOOL bResult = TRUE;

	while (bResult  && (*b != 0)) {
		Sleep(1);
		bResult = WriteFile(hCom,b,1,&wbytes, NULL);
		b++;
	}
	Sleep(1);
	bResult = WriteFile(hCom,&cr,1,&wbytes, NULL);
	printf("%c\n",wbytes);
	return 0;
}

void WriteInput()
{
	u8 b;
	while(Read(&b)) {
			//printf("0x%02X %c\n", b, b);
			printf("%c",b);
		}
}

void WriteInput1()
{
	u8 b;
	int i;
	for(i=0;i<1000000;i++)
	{
		if(Read(&b)) {
			printf("%c",b);
		}
	}
}


#define HIDP_TRANS_GET_REPORT    0x40
#define HIDP_TRANS_SET_REPORT    0x50
#define HIDP_DATA_RTYPE_INPUT    0x01
#define HIDP_DATA_RTYPE_OUTPUT   0x02
#define HIDP_DATA_RTYPE_FEATURE  0x03

char set03f4[] = { HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE, 0xf4, 0x42, 0x03, 0x00, 0x00 };

#define LED_PERMANENT 0xff, 0x27, 0x00, 0x00, 0x32
char set0201[] = {
  HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUTPUT, 0x01,
  0x00, 0x00, 0x00, 0,0, 0x00, 0x00, 0x00,
  0x00, 0x03 /*LED*/,
  LED_PERMANENT,
  LED_PERMANENT,
  LED_PERMANENT,
  LED_PERMANENT,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};


void main(void)
{
	OpenPort();
	WriteLine("");
	
	WriteLine("SET CONTROL MUX 1");	
	Sleep(1000);
	WriteInput();
	WriteMux(0xff, "L2CAP 13", 8);
	Sleep(1000);
	WriteInput();
	WriteMux(0xff,"L2CAP 11", 8);
	Sleep(1000);	
	WriteInput();
	WriteMux(0x00, set03f4, 6);

	WriteInput1();

	WriteMux(0xff, "SET CONTROL MUX 0", 17);
	CloseHandle(hCom);
}